home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / amiga / gcctls92.lha / hunk2gcc / hunk2gcc.c < prev    next >
C/C++ Source or Header  |  1992-04-20  |  29KB  |  992 lines

  1. ;/* how to compile this thingy:
  2. gcc2 -O2 -msmall-code -resident hunk2gcc.c -o hunk2gcc -DNDEBUG
  3. quit
  4. */
  5.  
  6. /*
  7.  * Convert amiga object files in the hunk format into a.out-object files.
  8.  * ALINK style (ie. concatenated) libraries are supported as well, in that
  9.  * case a collection of object files is generated, you'll have to run
  10.  * `ar rs libfoo.a obj.*' on them to make an a.out-style library out of 
  11.  * them.
  12.  *
  13.  * Currently untested are:
  14.  *  o  base-relative relocs and references
  15.  *     I'll first have to teach gnu-ld how to deal with them ;-)
  16.  *  o  conversion of load files...
  17.  *  o  common symbols, amiga objects normally don't use them, sigh
  18.  *
  19.  * Currently not implemented are:
  20.  *  o  BLINK style indexed libraries (HUNK_LIB and HUNK_INDEX). If you're
  21.  *     generating such libraries yourself, you can as well generate oldstyle
  22.  *     libraries, and the libraries from Commodore-Amiga are in ALINK format
  23.  *     (amiga.lib and friends).
  24.  *     This index-format is so weird and complicated that I didn't bother
  25.  *     long to decide not to support it. If someone volunteers (you got
  26.  *     the source;-)) please send me enhancements!
  27.  *
  28.  * V1.0  91-10-08  M.Wild  first hack
  29.  * V1.1  91-10-19  M.Wild  add support for CHIP hunk attribute in
  30.  *               DATA/BSS hunks (not CODE, ever used??)
  31.  *               Now, when are multiple hunks supported ? ;-)
  32.  *
  33.  * This is free software. This means that I don't care what you do with it
  34.  * as long as you don't claim you wrote it. If you enhance it, please
  35.  * send me your diffs! 
  36.  * Oh, of course, you use this stuff entirely at your own risk, I'm not 
  37.  * responsible for any damage this program might cause to you, your computer,
  38.  * your data, your cat, your whateveryoucanthinkof, no warranty whatsoever is
  39.  * granted.
  40.  *
  41.  * I can be reached on internet as: wild@nessie.cs.id.ethz.ch (Markus Wild)
  42.  *
  43.  */
  44.  
  45. #include <sys/types.h>
  46. #include <sys/stat.h>
  47. #include <sys/file.h>
  48. #include <a.out.h>
  49. #include <stdio.h>
  50. #include <stdlib.h>
  51. #include <unistd.h>
  52. #include <string.h>
  53.  
  54. /* This is really <dos/doshunks.h>, which is a 2.0 header file.
  55.  * You can get those 2.0 headers from CATS.
  56.  * Sorry, I'm not allowed to include them here. You may as well take the
  57.  * AmigaDOS Manual 2nd ed. (you'll miss the a4-rel hunks) or 3rd ed. and write
  58.  * the header yourself, it's not that long and difficult
  59.  */
  60. #include "doshunks.h"
  61.  
  62. /* strangely enough, this is missing from the doshunks.h file */
  63. #define HUNK_ATTRIBUTE(h) ((h) >> 30)
  64. #define HUNK_VALUE(h) ((h) & 0x3fffffff)
  65. #define HUNK_ATTR_CHIP 0x01
  66.  
  67. /* These are the symbol names we are generating to denote the limit between
  68.  * the `normal' and `chip' data/bss.
  69.  */
  70. #define CHIP_DATA_START "__chip_data"
  71. #define CHIP_BSS_START  "__chip_bss"
  72.  
  73. #ifndef NDEBUG
  74. #define DP(a) printf a
  75. #else
  76. #define DP(a)
  77. #endif
  78.  
  79. /* don't introduce the same chaos as with gcc versions... this doesn't 
  80.  * include the `real' version, but the compilation date seems to be an
  81.  * even better way to distinguish versions.. */
  82. static char *version_tag = "\0$VER: hunk2gcc " __DATE__ "\r\n";
  83.  
  84. extern int errno;
  85.  
  86. /* my favorite typedefs ;-)) */
  87. typedef unsigned char uchar;
  88. typedef unsigned long ulong;
  89.  
  90. ulong *file_buf = 0;
  91.  
  92. /* if set no progress reports are output */
  93. int silent_mode = 0;
  94.  
  95. struct reloc {
  96.   /* at which offset to relocate */
  97.   int offset;
  98.   /* based on which hunk base */
  99.   int from_hunk, to_hunk;
  100.   int size;
  101.   int pcrel;
  102.   int baserel;
  103.   /* if != -1, the "to_hunk" field is not used */
  104.   int sym_num;
  105. };
  106.  
  107. /* NOTE: this symbol definition is compatible with struct nlist, and it will
  108.  * be converted into a struct nlist in 'emit_aout_obj' */
  109. struct symbol {
  110.   int   name;        /* string as offset into string table */
  111.   uchar type;
  112.   uchar pad1;        /* really n_other */
  113.   short hunk_num;    /* really n_desc  */
  114.   ulong value;
  115. };
  116.  
  117. struct table {
  118.   void *base;
  119.   int el_size;
  120.   int i;
  121.   int max_el;
  122. };
  123.  
  124. void
  125. emit_aout_file (int fd, void *text, void *data, void *chip_data,
  126.         struct exec *hdr, int chip_data_size, int chip_bss_size,
  127.         struct table *ch_tab, struct table *dh_tab, struct table *bh_tab,
  128.         struct table *cdh_tab, struct table *cbh_tab,
  129.         struct table *reloc_tab,  struct table *symbol_tab, int max_hunk);
  130.  
  131. #define TAB_START_SIZE 1024
  132.  
  133. /* advance the hunk-pointer to the next hunk. Assumes the hunk-pointer is
  134.  * pointing at the length-field currently
  135.  */
  136. static void inline 
  137. next_hunk(ulong **hp)
  138. {
  139.   /* skip over the length field and the there given length */
  140.   *hp += 1 + **hp;
  141. }
  142.  
  143.  
  144. /* save a lot of space for duplicate string, that all say "only.. with size.. */
  145. static void inline
  146. limit_hunk (char *hunk_name)
  147. {
  148.   fprintf (stderr, "only one %s hunk with size!=0 supported.\n", hunk_name);
  149. }
  150.  
  151. /****************************************************************************/
  152.  
  153. /* these two function maintain the string table. You may only free the last
  154.  * string allocated. (This could be done with an obstack as well, but I really
  155.  * don't need the whole functionality of an obstack, so I kept it simple ;-))
  156.  * Only use the offset, since the table itself may be reallocated.
  157.  */
  158. char *str_table = 0;
  159. int strtab_size, strtab_index;
  160.  
  161. static int inline
  162. stralloc (int len)
  163. {
  164.   int res;
  165.  
  166.   /* always include the zero terminator */
  167.   len++;
  168.  
  169.   if (! str_table)
  170.     {
  171.       strtab_size = TAB_START_SIZE;
  172.       /* start the table at index 4, leaving space to later fill in the 
  173.        * size of the table */
  174.       strtab_index = 4;
  175.       str_table = malloc (strtab_size);
  176.     }
  177.  
  178.   while (strtab_index + len > strtab_size)
  179.     {
  180.       strtab_size <<= 1;
  181.       str_table = realloc (str_table, strtab_size);
  182.     }
  183.   
  184.   res = strtab_index;
  185.   strtab_index += len;
  186.   return res;
  187. }
  188.  
  189. static void inline
  190. strfree (int str)
  191. {
  192.   strtab_index = str;
  193. }
  194.  
  195. /****************************************************************************/
  196.  
  197. static void inline
  198. add_table (struct table *tab, void *el)
  199. {
  200.   if (tab->i == tab->max_el)
  201.     {
  202.       if (! tab->base)
  203.         {
  204.           tab->max_el = TAB_START_SIZE;
  205.           tab->base = malloc (tab->max_el * tab->el_size);
  206.         }
  207.       else
  208.     {
  209.       tab->max_el <<= 1;
  210.       tab->base = realloc (tab->base, tab->max_el * tab->el_size);
  211.     }
  212.       if (! tab->base)
  213.         {
  214.       fprintf (stderr, "Out of memory adding to table.\n");
  215.       /* exit does close all outstanding files ;-) */
  216.       exit (20);
  217.     }
  218.     }
  219.   bcopy (el, (uchar *)tab->base + (tab->i++ * tab->el_size), tab->el_size);
  220. }
  221.  
  222. static void inline
  223. add_reloc (struct table *tab, int from, int to, int offset,
  224.            int size, int pcrel, int baserel, int sym_num)
  225. {
  226.   struct reloc r;
  227.  
  228. DP(("reloc: from=%d, to=%d, off=%d, size=%d, pc=%d, ba=%d, syn=%d\n",
  229.     from, to, offset, size, pcrel, baserel, sym_num));
  230.  
  231.   r.from_hunk = from;
  232.   r.to_hunk   = to;
  233.   r.offset    = offset;
  234.   r.size      = size;
  235.   r.pcrel     = pcrel;
  236.   r.baserel   = baserel;
  237.   r.sym_num   = sym_num;
  238.   add_table (tab, &r);
  239. }
  240.  
  241. static void inline
  242. add_symbol (struct table *tab, int num, ulong type, int value, char *name)
  243. {
  244.   struct symbol s;
  245.   
  246.   s.hunk_num = num;
  247.   s.type     = type >> 24;
  248.   s.value    = value;
  249.   s.name     = stralloc ((type & 0xffffff)<<2);
  250.   bcopy (name, str_table+s.name, (type & 0xffffff)<<2);
  251.   (str_table+s.name)[(type & 0xffffff)<<2] = 0;
  252.   
  253.   /* some (really stupid..) compilers mention symbols twice, once as 
  254.    * a definition, and once as an EXT_SYMB. So we really have to search 
  255.    * the symbol_table before adding an EXT_SYMB and check if a symbol of this name
  256.    * isn't already defined for this value. If this hack should slow down
  257.    * the conversion dramatically, I'll have to resort to hashing, I don't
  258.    * like that idea... */
  259.   if (s.type == EXT_SYMB)
  260.     {
  261.       int i;
  262.       
  263.       for (i = 0; i < tab->i; i++)
  264.     /* we have CSE in the compiler, right? ;-)) */
  265.     if (((struct symbol *)tab->base)[i].value    == s.value    &&
  266.         ((struct symbol *)tab->base)[i].hunk_num == s.hunk_num &&
  267.         ! strcmp (str_table+((struct symbol *)tab->base)[i].name,
  268.               str_table+s.name))
  269.       {
  270.         strfree (s.name);
  271.         return;
  272.       }
  273.     }
  274.   
  275.   add_table (tab, &s);
  276. }
  277.  
  278. /****************************************************************************/
  279.  
  280. void
  281. digest_objfile (ulong **file_pptr, ulong *max_fp)
  282. {
  283.   /* this makes it less clumsy.. */
  284.   ulong *file_ptr = *file_pptr;
  285.   static int obj_file_num = 0;
  286.   int units = 0;
  287.   int fd = -1;
  288.   /* if processed hunk has a CHIP attribute */
  289.   int is_chip;
  290.   
  291.   /* buffer-pointers, where text & data sections are stored.
  292.    * Currently only one hunk with size!=0 of type text/data/bss each is
  293.    * supported.
  294.    * There is now an additional buffer to support one chip hunk as well.
  295.    * (chip-bss is supported too, but doesn't need a buffer ;-))
  296.    */
  297.   uchar *text, *data, *chip_data;
  298.   ulong chip_data_size, chip_bss_size;
  299.   struct exec hdr;
  300.   
  301.   /* hunk numbers, needed to associate reloc blocks with segments */ 
  302.   int hunk_num;
  303.   static struct table code_hunks      = { 0, 4, 0, 0 };
  304.   static struct table data_hunks      = { 0, 4, 0, 0 };
  305.   static struct table bss_hunks       = { 0, 4, 0, 0 };
  306.   static struct table chip_data_hunks = { 0, 4, 0, 0 };
  307.   static struct table chip_bss_hunks  = { 0, 4, 0, 0 };
  308.  
  309.   /* static so that no initialization code is required */
  310.   static struct table reloc_tab  = { 0, sizeof (struct reloc), 0, 0 };
  311.   static struct table symbol_tab = { 0, sizeof (struct symbol), 0, 0 };
  312.  
  313.   /* (re) init tables */
  314.   strtab_index = 4;
  315.   code_hunks.i =
  316.     data_hunks.i =
  317.       bss_hunks.i =
  318.         chip_data_hunks.i =
  319.           reloc_tab.i =
  320.             symbol_tab.i = 0;
  321.   
  322.   
  323.   while (units < 2)
  324.     {
  325.       switch (HUNK_VALUE(*file_ptr++))
  326.         {
  327.         case HUNK_UNIT:
  328. DP(("HUNK_UNIT: units = %d\n", units));
  329.           if (units++) break;
  330. #if 0
  331.       if (! file_ptr[0])
  332. #endif
  333.         {
  334.           /* need [], not *, so that gcc allocates a fresh copy for
  335.            * mkstemp() to modify! */
  336.           char tmp_nam[] = "obj.YYYY.XXXXXX";
  337.           /* this trick makes mkstemp() lots faster ;-) */
  338.           sprintf (tmp_nam, "obj.%04d.XXXXXX", obj_file_num++);
  339.           if ((fd = mkstemp (tmp_nam)) < 0)
  340.               fprintf (stderr, "Can't create %s (%s). Ignoring it.\n",
  341.                        tmp_nam, strerror (errno));
  342.         }
  343. #if 0
  344. /* this idea was too good.. there are so many stupid (and duplicate!) names
  345.  * of program units, that this generated ridiculous results... */
  346.  
  347.       else
  348.         {
  349.           char *file_name;
  350.           file_name = alloca (file_ptr[0] + 1);
  351.           strncpy (file_name, (char *)&file_ptr[1], file_ptr[0]);
  352.           if ((fd = open (file_name, O_RDWR|O_CREAT|O_EXCL, 0666)) < 0)
  353.               fprintf (stderr, "Can't create %s: %s. Ignoring it.\n",
  354.                        file_name, strerror (errno));
  355.         }
  356. #endif
  357.  
  358.       /* init data for new object file */
  359.       text = data = chip_data = 0;
  360.       bzero (&hdr, sizeof (hdr));
  361.       chip_data_size = chip_bss_size = 0;
  362.       /* if someone want's to use'em on a sun, why shouldn't we make
  363.        * the files sun-conformant? */
  364.       hdr.a_mid = MID_SUN010;
  365.       hdr.a_magic = OMAGIC;
  366.       hunk_num = 0;
  367.       next_hunk (& file_ptr);
  368.       if (! silent_mode)
  369.         {
  370.           putchar ('.');
  371.           fflush (stdout);
  372.         }
  373.       break;
  374.  
  375.         case HUNK_NAME:
  376.         case HUNK_DEBUG:
  377. DP(("HUNK_NAME/DEBUG\n"));
  378.       /* this hunk is silently ignored ;-) */
  379.       next_hunk (& file_ptr);
  380.       break;
  381.     
  382.         case HUNK_OVERLAY:
  383.           fprintf (stderr, "warning: overlay hunk ignored!\n");
  384.           next_hunk (& file_ptr);
  385.           break;
  386.         
  387.         case HUNK_BREAK:
  388.           fprintf (stderr, "warning: break hunk ignored!\n");
  389.       break;
  390.     
  391.         case HUNK_HEADER:
  392.           fprintf (stderr, "warning: load file header encountered.\n");
  393.           fprintf (stderr, "         are you sure this is an object file?\n");
  394.           /* nevertheless, we go on. perhaps some day I need this feature to
  395.            * be able to convert a loadfile into an object file?! */
  396.          
  397.           /* skip (never used) resident library names */
  398.           while (file_ptr[0]) next_hunk (& file_ptr);
  399.           /* skip null-word, table_size, F & L, and size-table */
  400.           file_ptr += 4 + (file_ptr[1] - file_ptr[2] + 1);
  401.           break;
  402.         
  403.         case HUNK_CODE:
  404. DP(("HUNK_CODE, size = $%x\n", file_ptr[0] << 2));
  405.       is_chip = HUNK_ATTRIBUTE(file_ptr[-1]) == HUNK_ATTR_CHIP;
  406.       if (is_chip)
  407.         fprintf (stderr, "CHIP code hunks are not supported, "
  408.                  "ignoring CHIP attribute\n");
  409.       if (file_ptr[0])
  410.         {
  411.           /* only accept one code hunk with size != 0 */
  412.           if (hdr.a_text)
  413.             limit_hunk ("code");
  414.           else
  415.             {
  416.                 text = (uchar *)&file_ptr[1];
  417.                 hdr.a_text = file_ptr[0] << 2;
  418.             }
  419.         }
  420.       next_hunk (& file_ptr);
  421.       add_table (& code_hunks, &hunk_num);
  422.       hunk_num++;
  423.       break;
  424.  
  425.         case HUNK_DATA:
  426. DP(("HUNK_DATA, size = $%x\n", file_ptr[0] << 2));
  427.       is_chip = HUNK_ATTRIBUTE(file_ptr[-1]) == HUNK_ATTR_CHIP;
  428.       if (file_ptr[0])
  429.         {
  430.           /* only accept one data hunk with size != 0 */
  431.           if (is_chip)
  432.         {
  433.           if (chip_data_size)
  434.             limit_hunk ("chip data");
  435.           else
  436.             {
  437.               chip_data = (uchar *) &file_ptr[1];
  438.               chip_data_size = file_ptr[0] << 2;
  439.             }
  440.         }
  441.           else
  442.         {
  443.               if (hdr.a_data)
  444.                 limit_hunk ("data");
  445.               else
  446.                 {
  447.                     data = (uchar *)&file_ptr[1];
  448.                     hdr.a_data = file_ptr[0] << 2;
  449.                 }
  450.             }
  451.         }
  452.       next_hunk (& file_ptr);
  453.       add_table (is_chip ? & chip_data_hunks : & data_hunks, & hunk_num);
  454.       hunk_num++;
  455.       break;
  456.  
  457.         case HUNK_BSS:
  458. DP(("HUNK_BSS, size = $%x\n", file_ptr[0] << 2));
  459.       is_chip = HUNK_ATTRIBUTE(file_ptr[-1]) == HUNK_ATTR_CHIP;
  460.       if (file_ptr[0])
  461.         {
  462.           /* only accept one bss hunk with size != 0 */
  463.           if (is_chip)
  464.         {
  465.           if (chip_bss_size)
  466.             limit_hunk ("chip bss");
  467.           else
  468.             chip_bss_size = file_ptr[0] << 2;
  469.         }
  470.           else
  471.         {
  472.           if (hdr.a_bss)
  473.             limit_hunk ("bss");
  474.           else
  475.             hdr.a_bss = file_ptr[0] << 2;
  476.         }
  477.         }
  478.       file_ptr++;
  479.       add_table (is_chip ? & chip_bss_hunks : & bss_hunks, & hunk_num);
  480.       hunk_num++;
  481.       break;
  482.  
  483.         case HUNK_RELOC8:
  484.         case HUNK_RELOC16:
  485.         case HUNK_RELOC32:
  486.         /* do they work like this? don't know... */
  487.         case HUNK_DREL8:
  488.         case HUNK_DREL16:
  489.         case HUNK_DREL32:
  490.       {
  491.         int size, brel;
  492.  
  493.         brel = file_ptr[-1] >= HUNK_DREL32;
  494.         size = (brel ? HUNK_DREL8 : HUNK_RELOC8) - file_ptr[-1];
  495. DP(("HUNK_RELOC/DREL ($%x), brel = %d, size = %d\n", file_ptr[-1], brel, size));
  496.                 
  497.         while (file_ptr[0])
  498.           {
  499.             long to_reloc = file_ptr[1];
  500.             long n        = file_ptr[0];
  501.  
  502.             while (n--)
  503.               /* amiga relocs are automatically pcrel, when size < 2
  504.            * according to the AmigaDOS-Manual 2nd ed. */
  505.               add_reloc (&reloc_tab, hunk_num-1, to_reloc, file_ptr[n+2],
  506.                          size, size != 2, brel, -1);
  507.         
  508.             file_ptr += file_ptr[0] + 2;
  509.           }
  510.       }
  511.           file_ptr++;
  512.           break;
  513.         
  514.         case HUNK_SYMBOL:
  515.         case HUNK_EXT:
  516. DP(("HUNK_SYMBOL/EXT\n"));
  517.       while (file_ptr[0])
  518.         {
  519.           int n, size, brel;
  520.  
  521. DP(("  EXT_: %d, %-*.*s\n", file_ptr[0] >> 24, 
  522.     4*(file_ptr[0] & 0xffffff), 4*(file_ptr[0] & 0xffffff), &file_ptr[1]));
  523.  
  524.           switch (file_ptr[0] >> 24)
  525.             {
  526.               case EXT_SYMB:
  527.               case EXT_DEF:
  528.               case EXT_ABS:
  529.               case EXT_RES:
  530.                 add_symbol (&symbol_tab, hunk_num-1, file_ptr[0], 
  531.                     file_ptr[1+(file_ptr[0] & 0xffffff)],
  532.                     (char *)&file_ptr[1]);
  533.             file_ptr += 2+(file_ptr[0] & 0xffffff);
  534.             break;
  535.           
  536.           case EXT_COMMON:
  537.             /* first define the common symbol, then add the relocs */
  538.             add_symbol (&symbol_tab, hunk_num-1, file_ptr[0], 
  539.                      file_ptr[1+(file_ptr[0] & 0xffffff)],
  540.                     (char *)&file_ptr[1]);
  541.             file_ptr += 2+(file_ptr[0] & 0xffffff);
  542.  
  543.             /* now the references, translated into relocs */
  544.             for (n = file_ptr[0]; n--; )
  545.               add_reloc (&reloc_tab, hunk_num - 1, -1, file_ptr[n],
  546.                      2, 0, 0, symbol_tab.i - 1);
  547.             next_hunk (&file_ptr);
  548.             break;
  549.           
  550.           case EXT_REF8:
  551.           case EXT_REF16:
  552.           case EXT_REF32:
  553.           case EXT_DEXT8:
  554.           case EXT_DEXT16:
  555.           case EXT_DEXT32:
  556.             size = file_ptr[0] >> 24;
  557.             brel = size >= EXT_DEXT32;
  558.             size = (size == EXT_REF32 || size == EXT_DEXT32) ? 2 :
  559.                  ((size == EXT_REF16 || size == EXT_DEXT16) ? 1 : 0);
  560.             /* first define the symbol (as undefined ;-)), 
  561.              * then add the relocs */
  562.             add_symbol (&symbol_tab, hunk_num-1, file_ptr[0], 
  563.                     0, (char *)&file_ptr[1]);
  564.             file_ptr += 1+(file_ptr[0] & 0xffffff);
  565.  
  566.             /* now the references, translated into relocs */
  567.             for (n = file_ptr[0]; n; n--)
  568.               add_reloc (&reloc_tab, hunk_num - 1, -1, file_ptr[n],
  569.                      size, size < 2, brel, symbol_tab.i - 1);
  570.             next_hunk (&file_ptr);
  571.             break;
  572.  
  573.           default:
  574.             fprintf (stderr, 
  575.                  "Unknown symbol type %d, don't know how to handle!\n",
  576.                  file_ptr[0] >> 24);
  577.             /* can't continue, don't know how much to advance the file_ptr
  578.              * to reach the next valid hunk/block */
  579.             exit(20);
  580.             }
  581.         }
  582.       file_ptr++;
  583.       break;
  584.  
  585.         case HUNK_END:
  586. DP(("HUNK_END\n"));
  587.       break;
  588.  
  589.     case HUNK_LIB:
  590.     case HUNK_INDEX:
  591.       fprintf (stderr, "Convert this library into ALINK (join type) format.\n");
  592.       exit (20);
  593.  
  594.     default:
  595.       fprintf (stderr, "Unknown hunk type $%x, unit offset = $%x.\n",
  596.              file_ptr[-1], ((file_ptr-1)-*file_pptr) * 2);
  597.       /* can't continue, don't know how much to advance the file_ptr
  598.        * to reach the next valid hunk/block */
  599.       exit(20);
  600.     }
  601.       
  602.       if (file_ptr >= max_fp) break;
  603.     }
  604.  
  605.   *file_pptr = file_ptr >= max_fp ? max_fp : file_ptr-1;
  606.  
  607.   if (fd != -1)
  608.     emit_aout_file (fd, text, data, chip_data,
  609.             & hdr, chip_data_size, chip_bss_size,
  610.                 & code_hunks, & data_hunks, & bss_hunks,
  611.             & chip_data_hunks, & chip_bss_hunks,
  612.                 & reloc_tab, & symbol_tab, hunk_num);
  613. }
  614.  
  615.  
  616. void
  617. emit_aout_file (int fd, void *text, void *data, void *chip_data,
  618.         struct exec *hdr, int chip_data_size, int chip_bss_size,
  619.         struct table *ch_tab, struct table *dh_tab, struct table *bh_tab,
  620.         struct table *cdh_tab, struct table *cbh_tab,
  621.         struct table *reloc_tab,  struct table *symbol_tab, int max_hunk)
  622. {
  623.   int *code_hunks = ch_tab->base;
  624.   int *data_hunks = dh_tab->base;
  625.   int *bss_hunks  = bh_tab->base;
  626.   int *chip_data_hunks = cdh_tab->base;
  627.   int *chip_bss_hunks  = cbh_tab->base;
  628.  
  629.   char htype[max_hunk];  
  630.   int i;
  631.   struct reloc *r;
  632.   struct symbol *s;
  633.   static struct table text_relocs = { 0, sizeof (struct relocation_info), 0, 0 };
  634.   static struct table data_relocs = { 0, sizeof (struct relocation_info), 0, 0 };
  635.  
  636.   text_relocs.i =
  637.     data_relocs.i = 0;
  638.  
  639.   /* convert hunk-numbers into N_TEXT,N_DATA,N_BSS types
  640.    * I temporarily use N_EXT to really mean `N_CHIP'
  641.    */
  642.   for (i = 0; i < ch_tab->i; i++) htype[code_hunks[i]] = N_TEXT;
  643.   for (i = 0; i < dh_tab->i; i++) htype[data_hunks[i]] = N_DATA;
  644.   for (i = 0; i < bh_tab->i; i++) htype[bss_hunks[i]]  = N_BSS;
  645.   for (i = 0; i < cdh_tab->i; i++) htype[chip_data_hunks[i]] = N_DATA|N_EXT;
  646.   for (i = 0; i < cbh_tab->i; i++) htype[chip_bss_hunks[i]]  = N_BSS|N_EXT;
  647.  
  648. #ifndef NDEBUG
  649.   for (i = 0; i < max_hunk; i++) DP(("htype[%d] = %d\n", i, htype[i]));
  650. #endif
  651.  
  652.   /* first conversion run. Change all hunk-numbers into N_TEXT, N_DATA and
  653.    * N_BSS rsp.
  654.    * (If you wanted to support multi-hunk files (ie. files with more than
  655.    * one code/data/bss hunk with size > 0) you'd want to do the necessary
  656.    * conversions here.)
  657.    * A less general solution is currently implemented: one chip data and one
  658.    * chip bss hunk are supported as well. Multiple hunks should work analogous,
  659.    * but with tables instead of variables like `chip_data_size' and `data'.
  660.    */
  661.   for (i = 0, r = (struct reloc *)reloc_tab->base; i < reloc_tab->i; i++, r++)
  662.     {
  663.       /* have to convert the destination hunk before the source hunk, since I
  664.        * need the information, whether I have to change a data or a chip data
  665.        * source. */
  666.  
  667.       /* Convert the destination hunk, if this is a local reloc. If it has
  668.        * an associated symbol, that symbol will be converted from CHIP to whatever
  669.        * is needed 
  670.        * If the target lies in a chip hunk, we have to change the offset in the
  671.        * source hunk to include the `hunk-gap' between source and target
  672.        */
  673.       if (r->to_hunk > -1)
  674.     {
  675.       /* the base address of the used source hunk */
  676.       void *base_hunk;
  677.       /* this is the mentioned hunk-gap */
  678.       ulong offset;
  679.  
  680.       switch (htype[r->from_hunk])
  681.         {
  682.         case N_TEXT:
  683.           base_hunk = text;
  684.           break;
  685.  
  686.         case N_DATA:
  687.           base_hunk = data;
  688.           break;
  689.           
  690.         case N_DATA|N_EXT:
  691.           base_hunk = chip_data;
  692.           break;
  693.  
  694.         default:
  695.           fprintf (stderr, "Local reloc from illegal hunk ($%x)!\n",
  696.                htype[r->from_hunk]);
  697.           break;
  698.         }
  699.  
  700.       /* account for an eventual shift of the former N_BSS space by
  701.        * chip_data_size bytes */
  702.       switch (htype[r->to_hunk])
  703.         {
  704.         /* those don't need a shift */
  705.         case N_TEXT:
  706.         case N_DATA:
  707.           offset = 0;
  708.           break;
  709.           
  710.         case N_BSS:
  711.           offset = chip_data_size;
  712.           break;
  713.           
  714.         case N_DATA|N_EXT:
  715.           offset = hdr->a_data;
  716.           break;
  717.           
  718.         case N_BSS|N_EXT:
  719.           offset = chip_data_size + hdr->a_bss;
  720.           break;
  721.         }
  722.  
  723. DP(("r->from = %d, r->to = %d, base = %d, offset = %d\n", r->from_hunk, r->to_hunk, htype[r->from_hunk], offset));
  724.  
  725.       /* I really don't know how much sense non-long relocs make here,
  726.        * but it's easy to support, so .. ;-) */
  727.       switch (r->size)
  728.         {
  729.         case 2:
  730.           *(long *)(base_hunk + r->offset)  += (long)offset;
  731.           break;
  732.  
  733.         case 1:
  734.           *(short *)(base_hunk + r->offset) += (short)offset;
  735.           break;
  736.       
  737.         case 0:
  738.           *(char *)(base_hunk + r->offset)  += (char)offset;
  739.           break;
  740.             }
  741.       
  742.           r->to_hunk = htype[r->to_hunk] & ~N_EXT;
  743.     }
  744.  
  745.       /* if it's a CHIP hunk, I have to increment the relocation address by 
  746.        * the size of the base hunk */
  747.       if (htype[r->from_hunk] & N_EXT)
  748.     {
  749.       /* only N_DATA should come here, since there is no such thing as a
  750.        * reloc originating from BSS space, but we nevertheless check for it.. */
  751.       if (htype[r->from_hunk] == (N_DATA|N_EXT))
  752.         r->offset += hdr->a_data;
  753.       else
  754.         fprintf (stderr, "Reloc from CHIP-BSS space, undefined!!\n");
  755.     }
  756.       r->from_hunk = htype[r->from_hunk] & ~N_EXT;
  757.  
  758.     }
  759.  
  760.     
  761.   /* now convert the symbols into nlist's */
  762.   for (i = 0, s = (struct symbol *)symbol_tab->base; i < symbol_tab->i; i++, s++)
  763.     {
  764.       int nl_type = 0;
  765.  
  766.       /* change hunk numbers into types */
  767.       s->hunk_num = htype[s->hunk_num];
  768.  
  769.       switch (s->type)
  770.     {
  771.     case EXT_DEF:
  772.       /* externally visible symbol */
  773.       nl_type = N_EXT;
  774.       /* fall into */
  775.     
  776.     case EXT_SYMB:
  777.       nl_type |= s->hunk_num & ~N_EXT;
  778.       /* adjust multi-hunk values to the one-seg model */
  779.       if (s->hunk_num == N_DATA)
  780.         s->value += hdr->a_text;
  781.       else if (s->hunk_num == N_BSS)
  782.         s->value += hdr->a_text + hdr->a_data + chip_data_size;
  783.       else if (s->hunk_num == (N_DATA|N_EXT))
  784.         s->value += hdr->a_text + hdr->a_data;
  785.       else if (s->hunk_num == (N_BSS|N_EXT))
  786.         s->value += hdr->a_text + hdr->a_data + chip_data_size + hdr->a_bss;
  787.       break;
  788.       
  789.     case EXT_ABS:
  790.       nl_type = N_ABS | N_EXT;
  791.       break;
  792.       
  793.     case EXT_COMMON:
  794.       /* ok for common as well, because the value field is only setup
  795.        * for common-symbols */
  796.  
  797.     case EXT_REF32:
  798.     case EXT_REF16:
  799.     case EXT_REF8:
  800.     case EXT_DEXT32:
  801.     case EXT_DEXT16:
  802.     case EXT_DEXT8:
  803.       nl_type = N_UNDF | N_EXT;
  804.       break;
  805.  
  806.     default:
  807.       fprintf (stderr, "What kind of symbol is THAT? (%d)\n", s->type);
  808.       break;
  809.     }
  810.  
  811.       s->type = nl_type;
  812.       s->pad1 = s->hunk_num = 0;  /* clear nl_other & nl_desc fields */
  813.     }
  814.     
  815.   /* now convert the reloc table. Adjust (like above) data/bss values to the
  816.    * one-segment model for local relocations */
  817.   for (i =  0, r = (struct reloc *)reloc_tab->base; i < reloc_tab->i; i++, r++)
  818.     {
  819.       struct relocation_info rel;
  820.       uchar *core_addr;
  821.       ulong delta;
  822.       
  823.       rel.r_address = r->offset;
  824.       core_addr = (r->from_hunk == N_TEXT) ? text : 
  825.             ((r->offset < hdr->a_data) ? data : chip_data);
  826.       /* r->offset has already been corrected to point at the chip data part
  827.        * appended to the data part. Since we don't physically join these
  828.        * segments (we just write them out after each other) we have to
  829.        * ignore these changes for patches, this is what DELTA is used for. */
  830.       delta = (core_addr == chip_data) ? hdr->a_data : 0;
  831.  
  832. DP(("r_add = $%x, core = %s, delta = %d, ", rel.r_address,
  833.    (core_addr == text) ? "text" : ((core_addr == data) ? "data" : "chip_data"),delta));
  834.  
  835.       if (r->to_hunk == N_DATA)
  836.     if (r->size == 2)
  837.           *(ulong *)(core_addr + rel.r_address - delta) += hdr->a_text;
  838.         else
  839.           fprintf (stderr, "%s reloc into N_DATA, what should I do?\n",
  840.            r->size == 1 ? "Short" : "Byte");
  841.       else if (r->to_hunk == N_BSS)
  842.     if (r->size == 2)
  843.           *(ulong *)(core_addr + rel.r_address - delta) += hdr->a_text + hdr->a_data;
  844.         else
  845.           fprintf (stderr, "%s reloc into N_BSS, what should I do?\n",
  846.            r->size == 1 ? "Short" : "Byte");
  847.  
  848. #if 0
  849.       /* don't know, what went wrong, but this conversion surely converts
  850.        * _LVO calls wrong. I'm sure leaving this out will generate other bugs..
  851.        * sigh... */
  852.  
  853.  
  854.       /* hmm... amigadog-hunks seem to do this in a strange way...
  855.        * Those relocs *are* treated as pcrel relocs by the linker (blink), 
  856.        * but they're not setup as such... geez, this hunk format.. */
  857.       if (r->pcrel)
  858.         switch (r->size)
  859.       {
  860.       case 2:
  861.         *(long *)(core_addr + rel.r_address  - delta) -= rel.r_address;
  862.         break;
  863.  
  864.       case 1:
  865.         *(short *)(core_addr + rel.r_address - delta) -= (short)rel.r_address;
  866.         break;
  867.         
  868.       case 0:
  869.         *(char *)(core_addr + rel.r_address  - delta) -= (char)rel.r_address;
  870.         break;
  871.       }
  872.  
  873. #endif
  874.  
  875.       rel.r_symbolnum = r->sym_num > -1 ? r->sym_num : r->to_hunk;
  876.       rel.r_pcrel     = r->pcrel;
  877.       rel.r_length    = r->size;
  878.       rel.r_extern    = r->sym_num > -1;
  879.       rel.r_baserel   = r->baserel;
  880.       rel.r_jmptable = /* rel.r_relative = */ 0;
  881.  
  882. DP(("r68: %s reloc\n", (r->from_hunk == N_TEXT) ? "text" : "data"));
  883.       add_table ((r->from_hunk == N_TEXT) ? & text_relocs : & data_relocs,
  884.             &rel);
  885.     }
  886.  
  887. DP(("r68: #tr = %d, #dr = %d\n", text_relocs.i, data_relocs.i));
  888.  
  889.   /* depending on whether we had any actual CHIP data, we have to adjust
  890.    * some of the header data, and we have to generate symbols containing the
  891.    * real size of the non-chip section(s) */
  892.   if (chip_data_size)
  893.     {
  894.       /* slightly different syntax, now that we directly add an nlist symbol */
  895.       add_symbol (symbol_tab, 0, (N_ABS << 24) | ((sizeof (CHIP_DATA_START)+3)>>2),
  896.           hdr->a_data, CHIP_DATA_START);
  897.       hdr->a_data += chip_data_size;
  898.     }
  899.   if (chip_bss_size)
  900.     {
  901.       add_symbol (symbol_tab, 0, (N_ABS << 24) | ((sizeof (CHIP_BSS_START)+3)>>2),
  902.           hdr->a_bss, CHIP_BSS_START);
  903.       hdr->a_bss  += chip_bss_size;
  904.     }
  905.  
  906.   /* oky, fill out the rest of the header and dump everything */
  907.   hdr->a_syms = symbol_tab->i * sizeof (struct nlist);
  908.   hdr->a_trsize = text_relocs.i * sizeof (struct relocation_info);
  909.   hdr->a_drsize = data_relocs.i * sizeof (struct relocation_info);
  910.   *(ulong *)str_table = strtab_index;
  911.   write (fd, (char *)hdr, sizeof (*hdr));
  912.   if (hdr->a_text) write (fd, text, hdr->a_text);
  913.   if (hdr->a_data - chip_data_size > 0)
  914.     write (fd, data, hdr->a_data - chip_data_size);
  915.   if (chip_data_size) write (fd, chip_data, chip_data_size);
  916.   if (hdr->a_trsize) write (fd, text_relocs.base, hdr->a_trsize);
  917.   if (hdr->a_drsize) write (fd, data_relocs.base, hdr->a_drsize);
  918.   if (hdr->a_syms) write (fd, symbol_tab->base, hdr->a_syms);
  919.   write (fd, str_table, strtab_index);
  920.   close (fd);
  921. }
  922.  
  923.  
  924.  
  925. int
  926. main (int argc, char *argv[])
  927. {
  928.   struct stat stb;
  929.   int ret_val = 0;
  930.   ulong *obj_pointer;
  931.   
  932.   FILE *fp;
  933.  
  934.   /* loop over all arguments. Can be either
  935.    *  o  object files
  936.    *  o  libraries (ALINK style for now)
  937.    */
  938.   while (*++argv)
  939.     {
  940.       if (! strcmp (*argv, "-s"))
  941.         {
  942.           silent_mode = 1;
  943.           continue;
  944.     }
  945.  
  946.       if (stat (*argv, &stb) == -1)
  947.         {
  948.           fprintf (stderr, "%s: %s\n", *argv, strerror (errno));
  949.           continue;
  950.         }
  951.       
  952.       file_buf = file_buf ? realloc (file_buf, stb.st_size) 
  953.               : malloc (stb.st_size);
  954.       if (! file_buf)
  955.         {
  956.           fprintf (stderr, "%s: can't allocate %d byte of memory.\n", 
  957.            *argv, stb.st_size);
  958.       ret_val = 20;
  959.       break;
  960.     }
  961.     
  962.       if (!(fp = fopen (*argv, "r")))
  963.         {
  964.           fprintf (stderr, "Can't open %s: %s.\n", *argv, strerror (errno));
  965.       continue;
  966.         }
  967.       
  968.       /* read the file in at once */
  969.       if (fread (file_buf, stb.st_size, 1, fp) != 1)
  970.         {
  971.       fprintf (stderr, "Can't read %s: %s.\n", *argv, strerror (errno));
  972.       fclose (fp);
  973.       continue;
  974.     }
  975.     
  976.       if (! silent_mode)
  977.         printf ("Converting %s:\n", *argv);
  978.  
  979.       /* oky, now digest the file (possibly more than one object file) */
  980.       for (obj_pointer = file_buf;
  981.        obj_pointer < (ulong *)((uchar *)file_buf + stb.st_size); )
  982.     digest_objfile (&obj_pointer, (ulong *)((uchar *)file_buf + stb.st_size));
  983.  
  984.       if (! silent_mode)
  985.         putchar ('\n');
  986.  
  987.       fclose (fp);
  988.     }
  989.  
  990.   return ret_val;
  991. }
  992.